using System;
using System.Collections.Generic;

namespace SharpGraphT.Sharp.System.Collections.Generic;

public static class DictionaryExtension {
    public static TV ComputeIfAbsent<TK, TV>(this IDictionary<TK, TV> d, TK key,
        Func<TK, TV> mappingFunction) {
        if (d.TryGetValue(key, out var value) && value != null) {
            return value;
        }

        value = mappingFunction(key);
        if (value != null) {
            d[key] = value;
        }

        return value;
    }

    public static bool TryGetValueUnordered<TK, TV>(
        this IDictionary<(TK, TK), TV> d, (TK, TK) key, out TV value) {
        var result1 = d.TryGetValue(key, out var value1);
        var result2 = d.TryGetValue((key.Item2, key.Item1), out var value2);

        if (result1 != result2) {
            throw new Exception("Inconsistent dictionary.");
        }

        if (!result1) {
            value = default;
            return false;
        }

        if (!value1.Equals(value2)) {
            throw new Exception("Inconsistent dictionary.");
        }

        value = value1;
        return true;
    }

    public static void SetValueUnordered<TK, TV>(
        this IDictionary<(TK, TK), TV> d, (TK, TK) key, TV value) =>
        d[(key.Item2, key.Item1)] = d[key] = value;

    public static bool RemoveUnordered<TK, TV>(this IDictionary<(TK, TK), TV> d,
        (TK, TK) key) =>
        d.TryGetValue(key, out var value1) ==
        d.TryGetValue((key.Item2, key.Item1), out var value2)
            ? d.Remove(key) && d.Remove((key.Item2, key.Item1))
            : throw new Exception("Inconsistent dictionary.");
}